package com.wf.demo.sys.controller;

import com.alibaba.fastjson.JSONObject;
import com.wf.demo.info.util.Result;
import com.wf.demo.job.util.RedisUtil;

import com.wf.demo.sys.constant.CommonConstant;
import com.wf.demo.sys.pojo.User;
import com.wf.demo.sys.pojo.UserTime;
import com.wf.demo.sys.service.UserLoginTimeService;
import com.wf.demo.sys.service.UserService;
import com.wf.demo.sys.shiro.ShiroUtils;
import com.wf.demo.sys.util.CommonUtils;
import com.wf.demo.sys.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;



/**
 * 登录相关
 *
 * @author Mark sunlightcs@gmail.com
 */
@Slf4j
@RestController
public class LoginController {

    @Autowired
    UserService userService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    UserLoginTimeService userLoginTimeService;


    /**
     * 登录
     */
    @PostMapping(value = "/login")
    public Result<JSONObject> login(@RequestBody User loginUser) {
        Result<JSONObject> result = new Result<JSONObject>();

        //1. 校验用户是否有效
        User sysUser = userService.getByName(loginUser.getUsername());
        System.out.println(loginUser.getUsername());
        if (sysUser==null) {
            return result.error500("用户不存在");
        }
        //账号锁定
        if(sysUser.getStatus() == 0){
            return result.error500("账号已被锁定,请联系管理员");
        }
        //2. 校验用户名或密码是否正确
        //先将提交的密码进行加密计算，再和数据库中的密码比对
        //取出随机数盐
        String salt =sysUser.getSalt() ;
        //加密
        int times = ShiroUtils.hashIterations;
        String algorithmName = ShiroUtils.hashAlgorithmName;
        //将新密码加密的密码
        String encodedPassword = new SimpleHash(algorithmName,loginUser.getPassword(), salt, times).toString();
        System.out.println("输入的密码是"+encodedPassword);
        //数据库中真正的密码
        String realPassword =sysUser.getPassword();
        System.out.println("正确的密码是"+realPassword);
        if (! encodedPassword.equals(realPassword)) {  //equalsIgnoreCase
            result.error500("用户名或密码错误");
            return result;
        }
        /**
         *  登录踢人功能，保证只能在一处地方登录
         *  如果用户上一次登录还未正常退出，redis保存有用户的上一次token，将该token清空
         * */
        //在redis中查找用户上一次的token
        String prefix = CommonConstant.PREFIX_USER_TOKEN+"*";//这个*一定要加，否则无法模糊查询
        Set<String> keys = redisUtil.keys(prefix);
        for(String key : keys){
            System.out.println("查询得到的key是"+key);
            //得到token值
            String tokenValue= (String) redisUtil.get(key);
            //如果该token中的用户名和这次登录的用户一样，就删除该token
            if( JwtUtil.getUsername(tokenValue).equals(loginUser.getUsername())){
                redisUtil.del(key);
                System.out.println("删除的token是"+tokenValue);
            }
        }
        /*******************************************/

        //用户登录信息
        userInfo(sysUser, result);  //生成新的token并保存

        return result;
    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping(value = "/logout")
    public Result<Object> logout(@RequestBody UserTime userTime, HttpServletRequest request, HttpServletResponse response) {
        //用户退出逻辑
        String token = request.getHeader(CommonConstant.ACCESS_TOKEN);
        System.out.println(token);
        if (CommonUtils.isEmpty(token)) {
            return Result.error("退出登录失败！");
        }
        String username = JwtUtil.getUsername(token);
        System.out.println(username);
        User  sysUser = userService.getByName(username);
        if (sysUser != null) {

            //清空用户Token缓存
            redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
            //清空用户权限缓存：权限Perms和角色集合,防止在缓存中的Perms未过期，重新登陆时角色权限未更新。
            redisUtil.del("shiro:cache:authorizationCache:"+ username);
          //  redisUtil.del("shiro:cache:authorizationCache:" + username);
            /**
             * 退出前先储存用户的在线时间信息
             * */
            List<UserTime> userTimeList=new ArrayList<>();
            //将新增的登录信息放入
            userTimeList.add(userTime);
            //得到在缓存中的登录信息list,如果不为空，放入新的总list中
            List<UserTime> oldList=( List<UserTime>) redisUtil.get("UserTime_"+username);
            if(null != oldList)
            userTimeList.addAll(oldList);
            System.out.println(" userTimeList中的长度为"+userTimeList.size());
            //储存 文件夹名是UserLoginTime
            redisUtil.set("UserLoginTime"  + ":"+"UserTime_"+username,userTimeList);
            /**
             * 用户登录时间和在线了多久的时间改为数据库储存
             *
             * */
            userLoginTimeService.add(userTime);

            return Result.ok("退出登录成功！");
        } else {
            return Result.error("无效的token");
        }
    }
    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(User sysUser, Result<JSONObject> result) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        // 设置超时时间          超时时间为多少？
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);

        // 获取用户公司信息
        JSONObject obj = new JSONObject();
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        result.setData(obj);
        result.success("登录成功");
        return result;
    }



}
